﻿using System;

// Holds information about the playing field. Row and Coll offsets are used to draw empty spaces between the squares with the formula (row + 1) * offset.
// All initial settings and initialization of the game field are done here.
public class GameBoard
{
    public int Rows { get; private set; }
    public int Cols { get; private set; }
    public int RowOffset { get; private set; }
    public int ColOffset { get; private set; }
    public int MinesCount { get; private set; }
    public Coords2D TimerLocation { get; private set; }
    public Coords2D GameOverLocation { get; private set; }
    private Square[,] Squares { get; set; }

    public GameBoard(int minesCount = 40, int rows = 10, int cols = 20, int rowOffset = 2, int colOffset = 3)
    {
        this.Rows = rows;
        this.Cols = cols;
        this.Squares = new Square[rows, cols];
        this.RowOffset = rowOffset;
        this.ColOffset = colOffset;
        this.MinesCount = minesCount;
        this.TimerLocation = new Coords2D(0, (cols - 1) * colOffset);
        this.GameOverLocation = new Coords2D(1, ((cols - 1) * colOffset) / 2 - 2);

        GenerateMines();
        FillOtherSquares();
    }

    public Square this[Coords2D coords]
    {
        get
        {
            return this.Squares[coords.Row, coords.Col];
        }
        private set
        {
            this.Squares[coords.Row, coords.Col] = value;
        }
    }

    private void GenerateMines()
    {
        for (int i = 0; i < MinesCount; i++)
        {
            Coords2D currentMine;

            do
            {
                currentMine = RandomMineGenerator.GetRandomCoords2D(this.Rows, this.Cols);
            }
            while (this[currentMine] is MineSquare);

            this[currentMine] = new MineSquare();
        }
    }

    private void FillOtherSquares()
    {
        for (int row = 0; row < this.Rows; row++)
        {
            for (int col = 0; col < this.Cols; col++)
            {
                Coords2D currentSquare = new Coords2D(row, col);

                if (this[currentSquare] is MineSquare)
                {
                    continue;
                }
                else
                {
                    int neighbouringMinesCount = CountNeighbouringMines(currentSquare);

                    if (neighbouringMinesCount == 0)
                    {
                        this[currentSquare] = new EmptySquare();
                    }
                    else
                    {
                        this[currentSquare] = new NumberSquare(neighbouringMinesCount);
                    }
                }
            }
        }
    }

    private int CountNeighbouringMines(Coords2D middleSquare)
    {
        int startRow = Math.Max(0, middleSquare.Row - 1);
        int endRow = Math.Min(this.Rows - 1, middleSquare.Row + 1);

        int startCol = Math.Max(0, middleSquare.Col - 1);
        int endCol = Math.Min(this.Cols - 1, middleSquare.Col + 1);

        int minesCount = 0;

        for (int row = startRow; row <= endRow; row++)
        {
            for (int col = startCol; col <= endCol; col++)
            {
                Coords2D currentSquare = new Coords2D(row, col);

                if (this[currentSquare] is MineSquare)
                {
                    minesCount++;
                }
            }
        }

        return minesCount;
    }
}
